home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1999 July: Mac OS SDK / Dev.CD Jul 99 SDK1.toast / Development Kits / Mac OS / Thread Manager / Sample Applications / 68k Examples / Traffic Threads / TrafficLight.c next >
Encoding:
C/C++ Source or Header  |  1994-11-17  |  27.8 KB  |  1,100 lines  |  [TEXT/MPS ]

  1. /*------------------------------------------------------------------------------
  2. #
  3. #    Apple Macintosh Developer Technical Support
  4. #
  5. #    MultiFinder-Aware Simple Sample Application
  6. #
  7. #
  8. ------------------------------------------------------------------------------*/
  9.  
  10.  
  11. #include <Values.h>
  12. #include <Types.h>
  13. #include <Resources.h>
  14. #include <QuickDraw.h>
  15. #include <Fonts.h>
  16. #include <Events.h>
  17. #include <Windows.h>
  18. #include <Menus.h>
  19. #include <TextEdit.h>
  20. #include <Dialogs.h>
  21. #include <Desk.h>
  22. #include <ToolUtils.h>
  23. #include <Memory.h>
  24. #include <SegLoad.h>
  25. #include <Files.h>
  26. #include <OSUtils.h>
  27. #include <OSEvents.h>
  28. #include <DiskInit.h>
  29. #include <Packages.h>
  30. #include <String.h>
  31. #include <Traps.h>
  32. #include <Threads.h>
  33. #include <stdio.h>
  34. #include <strings.h>
  35.  
  36. #include "TrafficLight.h"        /* bring in all the #defines for Sample */
  37.  
  38.  
  39. struct OurWindowInfoRec {
  40.     Boolean            stopped;
  41.     Boolean            timeToClose;
  42.     ThreadID        threadID;
  43.     };
  44.  
  45. typedef struct OurWindowInfoRec OurWindowInfoRec;
  46. typedef OurWindowInfoRec *OurWindowInfoRecPtr;
  47.  
  48.  
  49. SysEnvRec    gMac;                /* set up by Initialize */
  50.  
  51. Boolean        gInBackground;        /* maintained by Initialize and DoEvent */
  52.  
  53. Rect        gStopRect;            /* set up by Initialize */
  54. Rect        gGoRect;            /* set up by Initialize */
  55.  
  56. /* Dhrystone stuff */
  57. Rec_Pointer    Ptr_Glob, Next_Ptr_Glob;
  58. int            Int_Glob;
  59. Boolean        Bool_Glob;
  60. char        Ch_1_Glob, Ch_2_Glob;
  61. int            Arr_1_Glob [50];
  62. int            Arr_2_Glob [50] [50];
  63.  
  64. Boolean        DhrystoneDone;
  65. DialogPtr    DhrystoneDialog;
  66. int            DhrystoneCount;
  67. ThreadID    gDhrystoneThreadID;
  68. float        Microseconds, Dhrystones_Per_Second;
  69.  
  70. void Proc_1(Rec_Pointer Ptr_Val_Par);
  71. void Proc_2(One_Fifty *Int_Par_Ref);
  72. void Proc_3(Rec_Pointer *Ptr_Ref_Par);
  73. void Proc_4(void);
  74. void Proc_5(void);
  75. void Proc_6(Enumeration Enum_Val_Par, Enumeration *Enum_Ref_Par);
  76. void Proc_7(One_Fifty Int_1_Par_Val, One_Fifty Int_2_Par_Val, One_Fifty *Int_Par_Ref);
  77. void Proc_8(Arr_1_Dim Arr_1_Par_Ref, Arr_2_Dim Arr_2_Par_Ref, int Int_1_Par_Val, int Int_2_Par_Val);
  78. Enumeration Func_1(Capital_Letter Ch_1_Par_Val, Capital_Letter Ch_2_Par_Val);
  79. Boolean Func_2(Str_30 Str_1_Par_Ref, Str_30 Str_2_Par_Ref);
  80. Boolean Func_3(Enumeration Enum_Par_Val);
  81. pascal void * DhrystoneThread(void *threadParam);
  82. void Dhrystone(void);
  83.  
  84.  
  85. void EventLoop( void );
  86. void DoEvent( EventRecord *event );
  87. void AdjustCursor( Point mouse, RgnHandle region );
  88. void GetGlobalMouse( Point *mouse );
  89. void DoUpdate( WindowPtr window );
  90. void DoActivate( WindowPtr window, Boolean becomingActive );
  91. void DoContentClick( WindowPtr window );
  92. void DrawWindow( WindowPtr window );
  93. void AdjustMenus( void );
  94. void DoMenuCommand( long menuResult );
  95. void SetLight( WindowPtr window, Boolean newStopped );
  96. void DoCloseWindow( WindowPtr window );
  97. void DoNewWindow(void);
  98. pascal void * WindowThread(void *myWindow);
  99. void Terminate( void );
  100. void Initialize( void );
  101. Boolean GoGetRect( short rectID, Rect *theRect );
  102. void ForceEnvirons( void );
  103. Boolean IsAppWindow( WindowPtr window );
  104. Boolean IsDAWindow( WindowPtr window );
  105. Boolean TrapAvailable( short tNumber, TrapType tType );
  106. void AlertUser( void );
  107. void AlertUserContinue(short error);
  108. void MemClear(void *, unsigned long);
  109.  
  110.  
  111. /* Define HiWrd and LoWrd macros for efficiency. */
  112. #define HiWrd(aLong)    (((aLong) >> 16) & 0xFFFF)
  113. #define LoWrd(aLong)    ((aLong) & 0xFFFF)
  114.  
  115. /* Define TopLeft and BotRight macros for convenience. Notice the implicit
  116.    dependency on the ordering of fields within a Rect */
  117. #define TopLeft(aRect)    (* (Point *) &(aRect).top)
  118. #define BotRight(aRect)    (* (Point *) &(aRect).bottom)
  119.  
  120. extern void _DataInit();
  121.  
  122. #pragma segment Main
  123. main()
  124.     {
  125.     UnloadSeg((Ptr) _DataInit);        /* note that _DataInit must not be in Main! */
  126.     
  127.     MaxApplZone();                    /* expand the heap so code segments load at the top */
  128.  
  129.     Initialize();                    /* initialize the program */
  130.     UnloadSeg((Ptr) Initialize);    /* note that Initialize must not be in Main! */
  131.  
  132.     EventLoop();                    /* call the main event loop */
  133.     }
  134.  
  135.  
  136. #pragma segment Main
  137. void EventLoop()
  138. {
  139.     RgnHandle    cursorRgn;
  140.     Boolean        gotEvent;
  141.     EventRecord    event;
  142.     Point        mouse;
  143.  
  144.     cursorRgn = NewRgn();            /* we’ll pass WNE an empty region the 1st time thru */
  145.     do {
  146.         GetGlobalMouse(&mouse);
  147.         AdjustCursor(mouse, cursorRgn);
  148.         (void) ThreadBeginCritical();
  149.         gotEvent = DhrystoneDone;
  150.         (void) ThreadEndCritical();
  151.         if (gotEvent)
  152.             {
  153.             Str255 run;
  154.             Str255 result;
  155.             short typ;
  156.             Handle item;
  157.             Rect rect;
  158.             GrafPtr savePort;
  159.  
  160.             if (DhrystoneCount == 1)
  161.                 {
  162.                 Str255 s;
  163.                 GetIndString(&s, kDhrystoneString, 1);
  164.                 GetDItem(DhrystoneDialog, kMessageItem, &typ, &item, &rect);
  165.                 SetIText(item, s);
  166.                 }
  167.  
  168.             NumToString(DhrystoneCount, run);
  169.             sprintf((char*)result, "%f", Dhrystones_Per_Second);
  170.             c2pstr(result);
  171.             ParamText(run, result, nil, nil);
  172.             GetPort(&savePort);
  173.             SetPort(DhrystoneDialog);
  174.             GetDItem(DhrystoneDialog, kMessageItem, &typ, &item, &rect);
  175.             InvalRect(&rect);
  176.             SetPort(savePort);
  177.             DhrystoneDone = false;
  178.             DhrystoneCount += 1;
  179.             (void) SetThreadState(gDhrystoneThreadID, kReadyThreadState, kNoThreadID);
  180.             }
  181.         
  182.         gotEvent = WaitNextEvent(everyEvent, &event, 0, cursorRgn);
  183.         if (gotEvent == false)
  184.             (void) YieldToAnyThread();
  185.  
  186.         if ( gotEvent ) {
  187.             /* make sure we have the right cursor before handling the event */
  188.             AdjustCursor(event.where, cursorRgn);
  189.             DoEvent(&event);
  190.         }
  191.     } while ( true );    /* loop forever; we quit via ExitToShell */
  192. } /*EventLoop*/
  193.  
  194.  
  195. #pragma segment Main
  196. void DoEvent(event)
  197.     EventRecord    *event;
  198. {
  199.     short        part, err, dummyitem;
  200.     WindowPtr    window;
  201.     Boolean        hit;
  202.     char        key;
  203.     Point        aPoint;
  204.     DialogPtr    dummydialogptr;
  205.  
  206.     if ( event->what != keyDown && event->what != autoKey && IsDialogEvent(event) )
  207.         (void)DialogSelect(event, &dummydialogptr, &dummyitem);
  208.     else
  209.         switch ( event->what ) {
  210.             case mouseDown:
  211.                 part = FindWindow(event->where, &window);
  212.                 switch ( part ) {
  213.                     case inMenuBar:                /* process a mouse menu command (if any) */
  214.                         AdjustMenus();
  215.                         DoMenuCommand(MenuSelect(event->where));
  216.                         break;
  217.                     case inSysWindow:            /* let the system handle the mouseDown */
  218.                         SystemClick(event, window);
  219.                         break;
  220.                     case inContent:
  221.                         if ( window != FrontWindow() ) {
  222.                             SelectWindow(window);
  223.                             /*DoEvent(event);*/    /* use this line for "do first click" */
  224.                         } else
  225.                             DoContentClick(window);
  226.                         break;
  227.                     case inDrag:                /* pass screenBits.bounds to get all gDevices */
  228.                         DragWindow(window, event->where, &qd.screenBits.bounds);
  229.                         break;
  230.                     case inGrow:
  231.                         break;
  232.                     case inGoAway:
  233.                         DoCloseWindow(window);
  234.                         break;
  235.                     case inZoomIn:
  236.                     case inZoomOut:
  237.                         hit = TrackBox(window, event->where, part);
  238.                         if ( hit ) {
  239.                             SetPort(window);                /* the window must be the current port... */
  240.                             EraseRect(&window->portRect);    /* because of a bug in ZoomWindow */
  241.                             ZoomWindow(window, part, true);    /* note that we invalidate and erase... */
  242.                             InvalRect(&window->portRect);    /* to make things look better on-screen */
  243.                         }
  244.                         break;
  245.                 }
  246.                 break;
  247.             case keyDown:
  248.             case autoKey:                        /* check for menukey equivalents */
  249.                 key = event->message & charCodeMask;
  250.                 if ( event->modifiers & cmdKey )            /* Command key down */
  251.                     if ( event->what == keyDown ) {
  252.                         AdjustMenus();                        /* enable/disable/check menu items properly */
  253.                         DoMenuCommand(MenuKey(key));
  254.                     }
  255.                 break;
  256.             case activateEvt:
  257.                 DoActivate((WindowPtr) event->message, (event->modifiers & activeFlag) != 0);
  258.                 break;
  259.             case updateEvt:
  260.                 DoUpdate((WindowPtr) event->message);
  261.                 break;
  262.             case diskEvt:
  263.                 if ( HiWord(event->message) != noErr ) {
  264.                     SetPt(&aPoint, kDILeft, kDITop);
  265.                     err = DIBadMount(aPoint, event->message);
  266.                 }
  267.                 break;
  268.             case kOSEvent:
  269.                 switch ((event->message >> 24) & 0x0FF) {        /* high byte of message */
  270.                     case kSuspendResumeMessage:        /* suspend/resume is also an activate/deactivate */
  271.                         gInBackground = (event->message & kResumeMask) == 0;
  272.                         DoActivate(FrontWindow(), !gInBackground);
  273.                         break;
  274.                 }
  275.                 break;
  276.         }
  277. } /*DoEvent*/
  278.  
  279.  
  280. #pragma segment Main
  281. void AdjustCursor(mouse,region)
  282.     Point        mouse;
  283.     RgnHandle    region;
  284. {
  285.     WindowPtr    window;
  286.     RgnHandle    arrowRgn;
  287.     RgnHandle    plusRgn;
  288.     Rect        globalPortRect;
  289.  
  290.     window = FrontWindow();    /* we only adjust the cursor when we are in front */
  291.     if ( (! gInBackground) && (! IsDAWindow(window)) ) {
  292.         /* calculate regions for different cursor shapes */
  293.         arrowRgn = NewRgn();
  294.         plusRgn = NewRgn();
  295.  
  296.         /* start with a big, big rectangular region */
  297.         SetRectRgn(arrowRgn, kExtremeNeg, kExtremeNeg, kExtremePos, kExtremePos);
  298.  
  299.         /* calculate plusRgn */
  300.         if ( IsAppWindow(window) ) {
  301.             SetPort(window);    /* make a global version of the viewRect */
  302.             SetOrigin(-window->portBits.bounds.left, -window->portBits.bounds.top);
  303.             globalPortRect = window->portRect;
  304.             RectRgn(plusRgn, &globalPortRect);
  305.             SectRgn(plusRgn, window->visRgn, plusRgn);
  306.             SetOrigin(0, 0);
  307.         }
  308.  
  309.         /* subtract other regions from arrowRgn */
  310.         DiffRgn(arrowRgn, plusRgn, arrowRgn);
  311.  
  312.         /* change the cursor and the region parameter */
  313.         if ( PtInRgn(mouse, plusRgn) ) {
  314.             SetCursor(*GetCursor(plusCursor));
  315.             CopyRgn(plusRgn, region);
  316.         } else {
  317.             SetCursor(&qd.arrow);
  318.             CopyRgn(arrowRgn, region);
  319.         }
  320.  
  321.         /* get rid of our local regions */
  322.         DisposeRgn(arrowRgn);
  323.         DisposeRgn(plusRgn);
  324.     }
  325. } /*AdjustCursor*/
  326.  
  327.  
  328. #pragma segment Main
  329. void GetGlobalMouse(mouse)
  330.     Point    *mouse;
  331. {
  332.     EventRecord    event;
  333.     
  334.     OSEventAvail(kNoEvents, &event);    /* we aren't interested in any events */
  335.     *mouse = event.where;                /* just the mouse position */
  336. } /*GetGlobalMouse*/
  337.  
  338.  
  339. #pragma segment Main
  340. void DoUpdate(window)
  341.     WindowPtr    window;
  342. {
  343.     if ( IsAppWindow(window) ) {
  344.         BeginUpdate(window);                /* this sets up the visRgn */
  345.         if ( ! EmptyRgn(window->visRgn) )    /* draw if updating needs to be done */
  346.             DrawWindow(window);
  347.         EndUpdate(window);
  348.     }
  349. } /*DoUpdate*/
  350.  
  351.  
  352. #pragma segment Main
  353. void DoActivate(window, becomingActive)
  354.     WindowPtr    window;
  355.     Boolean        becomingActive;
  356. {
  357.     if ( IsAppWindow(window) ) {
  358.         if ( becomingActive )
  359.             /* do whatever you need to at activation */ ;
  360.         else
  361.             /* do whatever you need to at deactivation */ ;
  362.     }
  363. } /*DoActivate*/
  364.  
  365.  
  366. #pragma segment Main
  367. void DoContentClick(window)
  368.     WindowPtr    window;
  369. {
  370.     SetLight(window, ! ((OurWindowInfoRecPtr) (((WindowPeek) window)->refCon))->stopped);
  371. } /*DoContentClick*/
  372.  
  373.  
  374. #pragma segment Main
  375. void DrawWindow(window)
  376.     WindowPtr    window;
  377. {
  378.     SetPort(window);
  379.  
  380.     EraseRect(&window->portRect);    /* clear out any garbage that may linger */
  381.     if ( ((OurWindowInfoRecPtr) (((WindowPeek) window)->refCon))->stopped )                    /* draw a red (or white) stop light */
  382.         ForeColor(redColor);
  383.     else
  384.         ForeColor(whiteColor);
  385.     PaintOval(&gStopRect);
  386.     ForeColor(blackColor);
  387.     FrameOval(&gStopRect);
  388.     if ( ! ((OurWindowInfoRecPtr) (((WindowPeek) window)->refCon))->stopped )                /* draw a green (or white) go light */
  389.         ForeColor(greenColor);
  390.     else
  391.         ForeColor(whiteColor);
  392.     PaintOval(&gGoRect);
  393.     ForeColor(blackColor);
  394.     FrameOval(&gGoRect);
  395. } /*DrawWindow*/
  396.  
  397.  
  398. #pragma segment Main
  399. void AdjustMenus()
  400. {
  401.     WindowPtr    window;
  402.     MenuHandle    menu;
  403.  
  404.     window = FrontWindow();
  405.  
  406.     menu = GetMHandle(mFile);
  407.     EnableItem(menu, iNew);
  408.     if (window != nil)
  409.         EnableItem(menu, iClose);
  410.  
  411.     menu = GetMHandle(mEdit);
  412.     if ( IsDAWindow(window) ) {        /* a desk accessory might need the edit menu… */
  413.         EnableItem(menu, iUndo);
  414.         EnableItem(menu, iCut);
  415.         EnableItem(menu, iCopy);
  416.         EnableItem(menu, iClear);
  417.         EnableItem(menu, iPaste);
  418.     } else {                        /* …but we don’t use it */
  419.         DisableItem(menu, iUndo);
  420.         DisableItem(menu, iCut);
  421.         DisableItem(menu, iCopy);
  422.         DisableItem(menu, iClear);
  423.         DisableItem(menu, iPaste);
  424.     }
  425.  
  426. } /*AdjustMenus*/
  427.  
  428.  
  429. #pragma segment Main
  430. void DoMenuCommand(menuResult)
  431.     long        menuResult;
  432. {
  433.     short        menuID;                /* the resource ID of the selected menu */
  434.     short        menuItem;            /* the item number of the selected menu */
  435.     short        itemHit;
  436.     Str255        daName;
  437.     short        daRefNum;
  438.     Boolean        handledByDA;
  439.  
  440.     menuID = HiWord(menuResult);    /* use macros for efficiency to... */
  441.     menuItem = LoWord(menuResult);    /* get menu item number and menu number */
  442.     switch ( menuID ) {
  443.         case mApple:
  444.             switch ( menuItem ) {
  445.                 case iAbout:        /* bring up alert for About */
  446.                     itemHit = Alert(rAboutAlert, nil);
  447.                     break;
  448.                 default:            /* all non-About items in this menu are DAs */
  449.                     /* type Str255 is an array in MPW 3 */
  450.                     GetItem(GetMHandle(mApple), menuItem, daName);
  451.                     daRefNum = OpenDeskAcc(daName);
  452.                     break;
  453.             }
  454.             break;
  455.         case mFile:
  456.             switch ( menuItem ) {
  457.                 case iNew:
  458.                     DoNewWindow();
  459.                     break;
  460.                 case iClose:
  461.                     DoCloseWindow(FrontWindow());
  462.                     break;
  463.                 case iQuit:
  464.                     Terminate();
  465.                     break;
  466.             }
  467.             break;
  468.         case mEdit:                    /* call SystemEdit for DA editing & MultiFinder */
  469.             handledByDA = SystemEdit(menuItem-1);    /* since we don’t do any Editing */
  470.             break;
  471.         case mLight:
  472.             switch ( menuItem ) {
  473.                 case iStop:
  474.                     SetLight(FrontWindow(), true);
  475.                     break;
  476.                 case iGo:
  477.                     SetLight(FrontWindow(), false);
  478.                     break;
  479.             }
  480.             break;
  481.     }
  482.     HiliteMenu(0);                    /* unhighlight what MenuSelect (or MenuKey) hilited */
  483. } /*DoMenuCommand*/
  484.  
  485. /* Change the setting of the light. */
  486.  
  487. #pragma segment Main
  488. void SetLight( window, newStopped )
  489.     WindowPtr    window;
  490.     Boolean        newStopped;
  491. {
  492.     if ( newStopped != ((OurWindowInfoRecPtr) (((WindowPeek) window)->refCon))->stopped ) {
  493.         ((OurWindowInfoRecPtr) (((WindowPeek) window)->refCon))->stopped = newStopped;
  494.         SetPort(window);
  495.         InvalRect(&window->portRect);
  496.     }
  497. } /*SetLight*/
  498.  
  499. #pragma segment Main
  500. void
  501. DoNewWindow(void)
  502.     {
  503.     WindowPtr            window, tempWindow;            // temp window so we can dump it if NewWindow fails
  504.     OurWindowInfoRecPtr    windowInfoPtr;
  505.     ThreadID            theNewThread;
  506.         
  507.     if ( (window = tempWindow = (WindowPtr) NewPtr(sizeof(WindowRecord))) == nil )            // get window storage
  508.         goto ErrorHandler2;
  509.         
  510.     if ( (windowInfoPtr = (OurWindowInfoRecPtr) NewPtr(sizeof(OurWindowInfoRec))) == nil )    // get refCon storage
  511.         goto ErrorHandler2;
  512.  
  513.     MemClear(windowInfoPtr, sizeof(OurWindowInfoRec));                                    // Lazy way to init the fields        
  514.     windowInfoPtr->threadID = kNoThreadID;                                                // init the thread ID
  515.         
  516.     if ((window = GetNewWindow(rWindow, (Ptr) window, (WindowPtr) -1)) == nil)            // get the window
  517.         goto ErrorHandler1;
  518.     
  519.     ((WindowPeek) window)->refCon = windowInfoPtr;                                        // assign it to the window
  520.  
  521.     if (NewThread(kCooperativeThread, WindowThread, (void *) window, 0, (kUsePremadeThread), nil, &theNewThread) != noErr)
  522.         goto ErrorHandler1;
  523.     windowInfoPtr->threadID = theNewThread;                                                // assign real thread ID
  524.  
  525.     return;
  526.     
  527. ErrorHandler1:
  528.     CloseWindow(tempWindow);
  529. ErrorHandler2:
  530.     AlertUserContinue(eCommandFailed);
  531.     }
  532.  
  533. void
  534. DoCloseWindow(WindowPtr window)
  535.     {
  536.     if ( IsDAWindow(window) )
  537.         CloseDeskAcc(((WindowPeek) window)->windowKind);
  538.     else if ( IsAppWindow(window) )
  539.         ((OurWindowInfoRecPtr) (((WindowPeek) window)->refCon))->timeToClose = true;
  540.     } /*DoCloseWindow*/
  541.  
  542. #define TICKS        (*((unsigned long *) 0x16A))
  543.  
  544. pascal void *
  545. WindowThread(void *myWindow)
  546.     {
  547.     WindowPtr            window;
  548.     unsigned long        baseTicks, currTicks;
  549.     Boolean                toggle;
  550.     OurWindowInfoRecPtr    windowInfoPtr;
  551.     
  552.     window = (WindowPtr) myWindow;                                            // get the window
  553.     windowInfoPtr = (OurWindowInfoRecPtr) (((WindowPeek) window)->refCon);    // get the data (inited by DoNewWindow)
  554.  
  555.     baseTicks = TICKS;
  556.     toggle = false;
  557.     for (;;)
  558.         {
  559.         if (windowInfoPtr->timeToClose)
  560.             {
  561.             CloseWindow(window);
  562.             (void) DisposeThread(kCurrentThreadID, 0, true);    // and the lights go out...
  563.             }
  564.             
  565.         currTicks = TICKS;
  566.         if (baseTicks + 60 <= currTicks)
  567.             {
  568.             SetLight(window, toggle);
  569.             toggle = ! toggle;
  570.             baseTicks = currTicks;
  571.             }
  572.         
  573.         (void) YieldToAnyThread();
  574.         }
  575.     
  576.     return((void *) 'Wind');
  577.     }
  578.  
  579. #pragma segment Main
  580. void Terminate()
  581. {
  582.     WindowPtr    aWindow;
  583.     OSErr        myErr;
  584.     
  585.     while ((aWindow = FrontWindow()) != nil)
  586.         {
  587.         if (((WindowPeek) aWindow)->windowKind == dialogKind)
  588.             CloseDialog((DialogPtr) aWindow);
  589.         else
  590.             {
  591.             DoCloseWindow(aWindow);
  592.             myErr = YieldToThread(((OurWindowInfoRecPtr) (((WindowPeek) aWindow)->refCon))->threadID);
  593.             if (myErr) DebugStr ("\p Error from YieldToThread in Terminate()");
  594.             }
  595.         }
  596.  
  597.     ExitToShell();
  598. } /*Terminate*/
  599.  
  600.  
  601. #pragma segment Initialize
  602. void Initialize()
  603. {
  604.     Handle        menuBar;
  605.     EventRecord event;
  606.     short        count;
  607.  
  608.     gInBackground = false;
  609.     (void) CreateThreadPool(kCooperativeThread, 5, 0);
  610.     (void) CreateThreadPool(kPreemptiveThread, 1, 0);
  611.     InitGraf((Ptr) &qd.thePort);
  612.     InitFonts();
  613.     InitWindows();
  614.     InitMenus();
  615.     TEInit();
  616.     InitDialogs(nil);
  617.     InitCursor();
  618.     
  619.     for (count = 1; count <= 3; count++)
  620.         EventAvail(everyEvent, &event);
  621.     
  622.     SysEnvirons(kSysEnvironsVersion, &gMac);
  623.     
  624.     /* Make sure that the machine has at least 128K ROMs. If it doesn't, exit. */
  625.     
  626.     if (gMac.machineType < 0) AlertUser();
  627.     
  628.     menuBar = GetNewMBar(rMenuBar);            /* read menus into menu bar */
  629.     if ( menuBar == nil ) AlertUser();
  630.     SetMenuBar(menuBar);                    /* install menus */
  631.     DisposHandle(menuBar);
  632.     AddResMenu(GetMHandle(mApple), 'DRVR');    /* add DA names to Apple menu */
  633.     DrawMenuBar();
  634.     
  635.     if ( !GoGetRect(rStopRect, &gStopRect) )
  636.         AlertUser();                        /* the stop light rectangle */
  637.     if ( !GoGetRect(rGoRect, &gGoRect) )
  638.         AlertUser();                        /* the go light rectangle */
  639.  
  640.     DhrystoneDialog = GetNewDialog(kDhrystoneDLOG, nil, (WindowPtr)-1);
  641.  
  642.     DhrystoneCount = 1;
  643.     DhrystoneDone = false;
  644.     if (NewThread(kPreemptiveThread, DhrystoneThread, (void *) 0, 0, (kUsePremadeThread), nil, &gDhrystoneThreadID) != noErr)
  645.         AlertUser();
  646.  
  647. } /*Initialize*/
  648.  
  649.     
  650. #pragma segment Initialize
  651. Boolean GoGetRect(rectID,theRect)
  652.     short    rectID;
  653.     Rect    *theRect;
  654. {
  655.     Handle        resource;
  656.     
  657.     resource = GetResource('RECT', rectID);
  658.     if ( resource != nil ) {
  659.         *theRect = **((Rect**) resource);
  660.         return true;
  661.     }
  662.     else
  663.         return false;
  664. } /* GoGetRect */
  665.  
  666.  
  667. #pragma segment Main
  668. Boolean IsAppWindow(window)
  669.     WindowPtr    window;
  670. {
  671.     short        windowKind;
  672.  
  673.     if ( window == nil )
  674.         return false;
  675.     else {
  676.         windowKind = ((WindowPeek) window)->windowKind;
  677.         return (windowKind == userKind);
  678.     }
  679. } /*IsAppWindow*/
  680.  
  681.  
  682. #pragma segment Main
  683. Boolean IsDAWindow(window)
  684.     WindowPtr    window;
  685. {
  686.     if ( window == nil )
  687.         return false;
  688.     else    /* DA windows have negative windowKinds */
  689.         return ((WindowPeek) window)->windowKind < 0;
  690. } /*IsDAWindow*/
  691.  
  692.  
  693. #pragma segment Initialize
  694. Boolean TrapAvailable(tNumber,tType)
  695.     short        tNumber;
  696.     TrapType    tType;
  697. {
  698.     if ( ( tType == ToolTrap ) &&
  699.         ( gMac.machineType > envMachUnknown ) &&
  700.         ( gMac.machineType < envMacII ) ) {        /* it's a 512KE, Plus, or SE */
  701.         tNumber = tNumber & 0x03FF;
  702.         if ( tNumber > 0x01FF )                    /* which means the tool traps */
  703.             tNumber = _Unimplemented;            /* only go to 0x01FF */
  704.     }
  705.     return NGetTrapAddress(tNumber, tType) != GetTrapAddress(_Unimplemented);
  706. } /*TrapAvailable*/
  707.  
  708.  
  709. #pragma segment Main
  710.  
  711. /* -----------------------------------------------------------------------------
  712.  *
  713.  *                                Dhrystone.
  714.  *
  715.  * -----------------------------------------------------------------------------*/
  716.  
  717. pascal void *
  718. DhrystoneThread(void *threadParam)
  719.     {
  720. #pragma unused (threadParam)
  721.     for (;;)
  722.         {
  723.         Dhrystone();
  724.         (void) ThreadBeginCritical();
  725.         DhrystoneDone = true;
  726.         (void) ThreadEndCritical();
  727.         (void) SetThreadState(kCurrentThreadID, kStoppedThreadState, kNoThreadID);
  728.         }
  729.  
  730.     (void) DisposeThread(kCurrentThreadID, 0, true);
  731.     return((void *) 'Dhry');
  732.     }
  733.  
  734. void
  735. Dhrystone(void)
  736.     {
  737.     One_Fifty            Int_1_Loc;
  738.     register One_Fifty    Int_2_Loc;
  739.     One_Fifty            Int_3_Loc;
  740.     register char        Ch_Index;
  741.     Enumeration            Enum_Loc;
  742.     Str_30                Str_1_Loc;
  743.     Str_30                Str_2_Loc;
  744.     register int        Run_Index;
  745.     register int        Number_Of_Runs;
  746.     Rec_Type            fake_malloc1;
  747.     Rec_Type            fake_malloc2;
  748.  
  749.     unsigned long        Begin_Time, End_Time, User_Time;
  750.  
  751.     /* Initializations */
  752.  
  753.     Next_Ptr_Glob = (Rec_Pointer) &fake_malloc1;
  754.     Ptr_Glob = (Rec_Pointer) &fake_malloc2;
  755.  
  756.     Ptr_Glob->Ptr_Comp = Next_Ptr_Glob;
  757.     Ptr_Glob->Discr = Ident_1;
  758.     Ptr_Glob->variant.var_1.Enum_Comp = Ident_3;
  759.     Ptr_Glob->variant.var_1.Int_Comp = 40;
  760.     strcpy (Ptr_Glob->variant.var_1.Str_Comp, "DHRYSTONE PROGRAM, SOME STRING");
  761.     strcpy (Str_1_Loc, "DHRYSTONE PROGRAM, 1'ST STRING");
  762.  
  763.     /* Was missing in published program. Without this statement,    */
  764.     /* Arr_2_Glob [8][7] would have an undefined value.             */
  765.     /* Warning: With 16-Bit processors and Number_Of_Runs > 32000,  */
  766.     /* overflow may occur for this array element.                   */
  767.     Arr_2_Glob [8][7] = 10;
  768.  
  769.     Number_Of_Runs = 100000;
  770.  
  771.     /*********************/
  772.     /* Start timed tests */
  773.     /*********************/
  774.  
  775.     Begin_Time = TICKS;
  776.     for (Run_Index = 1; Run_Index <= Number_Of_Runs; ++Run_Index)
  777.         {
  778.         Proc_5();
  779.         Proc_4();
  780.         
  781.         /* Ch_1_Glob == 'A', Ch_2_Glob == 'B', Bool_Glob == true */
  782.         Int_1_Loc = 2;
  783.         Int_2_Loc = 3;
  784.         strcpy (Str_2_Loc, "DHRYSTONE PROGRAM, 2'ND STRING");
  785.         Enum_Loc = Ident_2;
  786.         Bool_Glob = ! Func_2 (Str_1_Loc, Str_2_Loc);
  787.         /* Bool_Glob == 1 */
  788.         
  789.         while (Int_1_Loc < Int_2_Loc) /* loop body executed once */
  790.             {
  791.             Int_3_Loc = 5 * Int_1_Loc - Int_2_Loc;
  792.             /* Int_3_Loc == 7 */
  793.             Proc_7 (Int_1_Loc, Int_2_Loc, &Int_3_Loc);
  794.             /* Int_3_Loc == 7 */
  795.             Int_1_Loc += 1;
  796.             } /* while */
  797.         
  798.         /* Int_1_Loc == 3, Int_2_Loc == 3, Int_3_Loc == 7 */
  799.         Proc_8 (Arr_1_Glob, Arr_2_Glob, Int_1_Loc, Int_3_Loc);
  800.         
  801.         /* Int_Glob == 5 */
  802.         Proc_1 (Ptr_Glob);
  803.         for (Ch_Index = 'A'; Ch_Index <= Ch_2_Glob; ++Ch_Index) /* loop executed twice */
  804.             {
  805.             if (Enum_Loc == Func_1 (Ch_Index, 'C')) /* then, not executed */
  806.                 {
  807.                 Proc_6 (Ident_1, &Enum_Loc);
  808.                 strcpy (Str_2_Loc, "DHRYSTONE PROGRAM, 3'RD STRING");
  809.                 Int_2_Loc = Run_Index;
  810.                 Int_Glob = Run_Index;
  811.                 }
  812.             }
  813.         
  814.         /* Int_1_Loc == 3, Int_2_Loc == 3, Int_3_Loc == 7 */
  815.         Int_2_Loc = Int_2_Loc * Int_1_Loc;
  816.         Int_1_Loc = Int_2_Loc / Int_3_Loc;
  817.         Int_2_Loc = 7 * (Int_2_Loc - Int_3_Loc) - Int_1_Loc;
  818.         
  819.         /* Int_1_Loc == 1, Int_2_Loc == 13, Int_3_Loc == 7 */
  820.         Proc_2 (&Int_1_Loc);
  821.         
  822.         /* Int_1_Loc == 5 */
  823.         
  824.          } /* loop "for Run_Index" */
  825.  
  826.     /********************/
  827.     /* Stop timed tests */
  828.     /********************/
  829.  
  830.     End_Time = TICKS;
  831.     User_Time = End_Time - Begin_Time;
  832.  
  833.     if (User_Time < Too_Small_Time)
  834.         Debugger();
  835.     else
  836.         {
  837.         Microseconds = (float) User_Time * Mic_secs_Per_Second / ((float) 60 * ((float) Number_Of_Runs));
  838.         Dhrystones_Per_Second = ((float) 60 * (float) Number_Of_Runs) / (float) User_Time;
  839.         }
  840.     
  841.     }
  842.  
  843. /* executed once */
  844. void
  845. Proc_1(register Rec_Pointer Ptr_Val_Par)
  846.     {
  847.     register Rec_Pointer    Next_Record;
  848.  
  849.     Next_Record = Ptr_Val_Par->Ptr_Comp; /* == Ptr_Glob_Next */
  850.  
  851.     /* Local variable, initialized with Ptr_Val_Par->Ptr_Comp,    */
  852.     /* corresponds to "rename" in Ada, "with" in Pascal           */
  853.     
  854.     *Ptr_Val_Par->Ptr_Comp = *Ptr_Glob; 
  855.     Ptr_Val_Par->variant.var_1.Int_Comp = 5;
  856.     Next_Record->variant.var_1.Int_Comp = Ptr_Val_Par->variant.var_1.Int_Comp;
  857.     Next_Record->Ptr_Comp = Ptr_Val_Par->Ptr_Comp;
  858.     Proc_3 (&Next_Record->Ptr_Comp);
  859.     /* Ptr_Val_Par->Ptr_Comp->Ptr_Comp == Ptr_Glob->Ptr_Comp */
  860.  
  861.     if (Next_Record->Discr == Ident_1) /* then, executed */
  862.         {
  863.         Next_Record->variant.var_1.Int_Comp = 6;
  864.         Proc_6 (Ptr_Val_Par->variant.var_1.Enum_Comp, &Next_Record->variant.var_1.Enum_Comp);
  865.         Next_Record->Ptr_Comp = Ptr_Glob->Ptr_Comp;
  866.         Proc_7 (Next_Record->variant.var_1.Int_Comp, 10, &Next_Record->variant.var_1.Int_Comp);
  867.         }
  868.     else /* not executed */
  869.         *Ptr_Val_Par = *Ptr_Val_Par->Ptr_Comp;
  870.     } /* Proc_1 */
  871.  
  872.  
  873. /* executed once */
  874. /* *Int_Par_Ref == 1, becomes 4 */
  875. void
  876. Proc_2(One_Fifty *Int_Par_Ref)
  877.     {
  878.     One_Fifty  Int_Loc;  
  879.     Enumeration   Enum_Loc;
  880.     
  881.     Int_Loc = *Int_Par_Ref + 10;
  882.     do /* executed once */
  883.     if (Ch_1_Glob == 'A') /* then, executed */
  884.         {
  885.         Int_Loc -= 1;
  886.         *Int_Par_Ref = Int_Loc - Int_Glob;
  887.         Enum_Loc = Ident_1;
  888.         } /* if */
  889.     
  890.     while (Enum_Loc != Ident_1); /* true */
  891.     } /* Proc_2 */
  892.  
  893.  
  894. /* executed once */
  895. /* Ptr_Ref_Par becomes Ptr_Glob */
  896. void
  897. Proc_3(Rec_Pointer *Ptr_Ref_Par)
  898.     {
  899.     if (Ptr_Glob != nil) /* then, executed */
  900.         *Ptr_Ref_Par = Ptr_Glob->Ptr_Comp;
  901.     Proc_7 (10, Int_Glob, &Ptr_Glob->variant.var_1.Int_Comp);
  902.     } /* Proc_3 */
  903.  
  904.  
  905. /* executed once */
  906. void
  907. Proc_4(void)
  908.     {
  909.     Boolean Bool_Loc;
  910.     
  911.     Bool_Loc = Ch_1_Glob == 'A';
  912.     Bool_Glob = Bool_Loc | Bool_Glob;
  913.     Ch_2_Glob = 'B';
  914.     } /* Proc_4 */
  915.  
  916.  
  917. /* executed once */
  918. void
  919. Proc_5(void)
  920.     {
  921.     Ch_1_Glob = 'A';
  922.     Bool_Glob = false;
  923.     } /* Proc_5 */
  924.  
  925. /* executed once */
  926. /* Enum_Val_Par == Ident_3, Enum_Ref_Par becomes Ident_2 */
  927. void
  928. Proc_6(Enumeration Enum_Val_Par, Enumeration *Enum_Ref_Par)
  929.     {
  930.     *Enum_Ref_Par = Enum_Val_Par;
  931.     if (! Func_3 (Enum_Val_Par)) /* then, not executed */
  932.         *Enum_Ref_Par = Ident_4;
  933.     switch (Enum_Val_Par)
  934.         {
  935.         case Ident_1: 
  936.             *Enum_Ref_Par = Ident_1;
  937.             break;
  938.         case Ident_2: 
  939.             if (Int_Glob > 100)
  940.                   *Enum_Ref_Par = Ident_1;
  941.             else
  942.                 *Enum_Ref_Par = Ident_4;
  943.             break;
  944.         case Ident_3: /* executed */
  945.             *Enum_Ref_Par = Ident_2;
  946.             break;
  947.         case Ident_4: break;
  948.         case Ident_5: 
  949.             *Enum_Ref_Par = Ident_3;
  950.             break;
  951.         } /* switch */
  952.     } /* Proc_6 */
  953.  
  954.  
  955. /* executed three times                                      */ 
  956. /* first call:      Int_1_Par_Val == 2, Int_2_Par_Val == 3,  */
  957. /*                  Int_Par_Ref becomes 7                    */
  958. /* second call:     Int_1_Par_Val == 10, Int_2_Par_Val == 5, */
  959. /*                  Int_Par_Ref becomes 17                   */
  960. /* third call:      Int_1_Par_Val == 6, Int_2_Par_Val == 10, */
  961. /*                  Int_Par_Ref becomes 18                   */
  962. void
  963. Proc_7 (One_Fifty Int_1_Par_Val, One_Fifty Int_2_Par_Val, One_Fifty *Int_Par_Ref)
  964.     {
  965.     One_Fifty Int_Loc;
  966.     
  967.     Int_Loc = Int_1_Par_Val + 2;
  968.     *Int_Par_Ref = Int_2_Par_Val + Int_Loc;
  969.     } /* Proc_7 */
  970.  
  971.  
  972. /* executed once      */
  973. /* Int_Par_Val_1 == 3 */
  974. /* Int_Par_Val_2 == 7 */
  975. void
  976. Proc_8 (Arr_1_Dim Arr_1_Par_Ref, Arr_2_Dim Arr_2_Par_Ref, int Int_1_Par_Val, int Int_2_Par_Val)
  977.     {
  978.     register One_Fifty Int_Index;
  979.     register One_Fifty Int_Loc;
  980.  
  981.     Int_Loc = Int_1_Par_Val + 5;
  982.     Arr_1_Par_Ref [Int_Loc] = Int_2_Par_Val;
  983.     Arr_1_Par_Ref [Int_Loc+1] = Arr_1_Par_Ref [Int_Loc];
  984.     Arr_1_Par_Ref [Int_Loc+30] = Int_Loc;
  985.     for (Int_Index = Int_Loc; Int_Index <= Int_Loc+1; ++Int_Index)
  986.         Arr_2_Par_Ref [Int_Loc] [Int_Index] = Int_Loc;
  987.     Arr_2_Par_Ref [Int_Loc] [Int_Loc-1] += 1;
  988.     Arr_2_Par_Ref [Int_Loc+20] [Int_Loc] = Arr_1_Par_Ref [Int_Loc];
  989.     Int_Glob = 5;
  990.     } /* Proc_8 */
  991.  
  992.  
  993. /* executed three times                                         */
  994. /* first call:      Ch_1_Par_Val == 'H', Ch_2_Par_Val == 'R'    */
  995. /* second call:     Ch_1_Par_Val == 'A', Ch_2_Par_Val == 'C'    */
  996. /* third call:      Ch_1_Par_Val == 'B', Ch_2_Par_Val == 'C'    */
  997. Enumeration
  998. Func_1 (Capital_Letter Ch_1_Par_Val, Capital_Letter Ch_2_Par_Val)
  999.     {
  1000.     Capital_Letter        Ch_1_Loc;
  1001.     Capital_Letter        Ch_2_Loc;
  1002.     
  1003.     Ch_1_Loc = Ch_1_Par_Val;
  1004.     Ch_2_Loc = Ch_1_Loc;
  1005.     if (Ch_2_Loc != Ch_2_Par_Val) /* then, executed */
  1006.         return (Ident_1);
  1007.     else  /* not executed */
  1008.         {
  1009.         Ch_1_Glob = Ch_1_Loc;
  1010.         return (Ident_2);
  1011.         }
  1012.     } /* Func_1 */
  1013.  
  1014.  
  1015. /* executed once */
  1016. /* Str_1_Par_Ref == "DHRYSTONE PROGRAM, 1'ST STRING" */
  1017. /* Str_2_Par_Ref == "DHRYSTONE PROGRAM, 2'ND STRING" */
  1018. Boolean
  1019. Func_2 (Str_30 Str_1_Par_Ref, Str_30 Str_2_Par_Ref)
  1020.     {
  1021.     register One_Thirty        Int_Loc;
  1022.     Capital_Letter            Ch_Loc;
  1023.  
  1024.     Int_Loc = 2;
  1025.     while (Int_Loc <= 2) /* loop body executed once */
  1026.         {
  1027.         if (Func_1 (Str_1_Par_Ref[Int_Loc], Str_2_Par_Ref[Int_Loc+1]) == Ident_1) /* then, executed */
  1028.             {
  1029.             Ch_Loc = 'A';
  1030.             Int_Loc += 1;
  1031.             }
  1032.         }
  1033.  
  1034.     if (Ch_Loc >= 'W' && Ch_Loc < 'Z') /* then, not executed */
  1035.         Int_Loc = 7;
  1036.  
  1037.     if (Ch_Loc == 'R') /* then, not executed */
  1038.         return (true);
  1039.     else /* executed */
  1040.         {
  1041.         if (strcmp (Str_1_Par_Ref, Str_2_Par_Ref) > 0)
  1042.             /* then, not executed */
  1043.             {
  1044.             Int_Loc += 7;
  1045.             Int_Glob = Int_Loc;
  1046.             return (true);
  1047.             }
  1048.         else /* executed */
  1049.             return (false);
  1050.         } /* if Ch_Loc */
  1051. } /* Func_2 */
  1052.  
  1053.  
  1054. /* Func_3. Whether Enum_Par_Val == Ident_3 */
  1055. Boolean
  1056. Func_3 (Enumeration Enum_Par_Val)
  1057.     {
  1058.     Enumeration Enum_Loc;
  1059.  
  1060.     Enum_Loc = Enum_Par_Val;
  1061.     return (Enum_Loc == Ident_3);
  1062.     } /* Func_3 */
  1063.  
  1064. /* -----------------------------------------------------------------------------
  1065.  *
  1066.  *                                Utility routines.
  1067.  *
  1068.  * -----------------------------------------------------------------------------*/
  1069.  
  1070. void
  1071. AlertUserContinue(short error)
  1072.     {
  1073.     Str255        message;
  1074.  
  1075.     SetCursor(&qd.arrow);
  1076.     GetIndString(message, kErrStrings, error);
  1077.     ParamText(message, "", "", "");
  1078.     (void) Alert(rUserAlert, nil);
  1079.     }
  1080.  
  1081. void AlertUser()
  1082. {
  1083.     short        itemHit;
  1084.  
  1085.     SetCursor(&qd.arrow);
  1086.     itemHit = Alert(rUserAlert, nil);
  1087.     ExitToShell();
  1088. } /* AlertUser */
  1089.     
  1090. /* MemClear.  Two-bit routine to clear 'bytes' bytes starting at *'ptr' */
  1091. void    
  1092. MemClear(register void *ptr, register unsigned long bytes)
  1093.     {
  1094.     do
  1095.         {
  1096.         *((char *) ptr)++ = (char) 0x00;
  1097.         }
  1098.     while (--bytes != 0);
  1099.     }
  1100.